package blue.http.internal.core.parser;

import blue.http.core.filter.HttpFilter;
import blue.http.core.filter.WebSocketFilter;
import blue.http.core.parser.FilterConfig;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;

/**
 * @author Jin Zheng
 * @since 1.0 2020-08-28
 */
public class FilterConfigCache {
	private List<FilterConfig> httpFilterList = new ArrayList<>();
	private List<FilterConfig> webSocketFilterList = new ArrayList<>();
	private AntPathMatcher pathMatcher = new AntPathMatcher();

	public FilterConfigCache() {
	}

	public void addFilterConfig(FilterConfig config) {
		Object target = config.getTarget();
		if (target instanceof HttpFilter) {
			httpFilterList.add(config);
			Collections.sort(httpFilterList);
		} else if (target instanceof WebSocketFilter) {
			webSocketFilterList.add(config);
			Collections.sort(webSocketFilterList);
		}
	}

	public List<HttpFilter> matchHttpFilter(String url) {
		return this.matchFilter(url, httpFilterList, t -> (HttpFilter) t.getTarget());
	}

	public List<WebSocketFilter> matchWebSocketFilter(String url) {
		return this.matchFilter(url, webSocketFilterList, t -> (WebSocketFilter) t.getTarget());
	}

	private <T> List<T> matchFilter(String url, List<FilterConfig> set, Function<FilterConfig, T> f) {
		List<T> list = new ArrayList<>();
		for (FilterConfig config : set) {
			boolean isExclude = false;
			for (String exclude : config.getExcludes()) {
				if (pathMatcher.match(exclude, url)) {
					isExclude = true;
					break;
				}
			}
			if (isExclude) {
				continue;
			}

			for (String include : config.getFilters()) {
				if (pathMatcher.match(include, url)) {
					list.add(f.apply(config));
					break;
				}
			}
		}
		return list;
	}

	public List<FilterConfig> all() {
		List<FilterConfig> list = new ArrayList<>(httpFilterList);
		list.addAll(webSocketFilterList);
		return list;
	}

}
